
import java.util.ArrayList;
import java.util.Collections;

/**
 * Hand object, creates 5 cards in the constructor.
 * 
 * @author James Knight
 * 
 */
public class Hand 
{
	private ArrayList<Card> hand = new ArrayList<Card>();

	/**
	 * Constructors for 5 different cards
	 */

	public Hand(Card one, Card two, Card three, Card four, Card five) 
	{
		hand.add(one);
		hand.add(two);
		hand.add(three);
		hand.add(four);
		hand.add(five);
		Collections.sort(hand);
	}

	/**
	 * Method uses to replace the user selected card and give them a new one.
	 * 
	 * @param discardNo - card to replace
	 * @param replace - replaces the selected card
	 */

	public Card replace(int discardNo, Card replace) 
	{
		Card discarded = hand.get(discardNo - 1);
		hand.set(discardNo - 1, replace);
		return discarded;
	}

	/**
	 * Returns a string representing the 5 cards.
	 */

	public String toString() 
	{
		return hand.toString();
	}

	/**
	 * Sorts the hand.
	 */

	public void sort() 
	{
		Collections.sort(hand);
	}

	/**
	 * Get's the size of the current hand.
	 */

	public int getSize() 
	{
		return hand.size();
	}

	/**
	 * Get's the card index.
	 * 
	 * @param index - get's the card index and returns it
	 */

	public Card getCard(int index) 
	{
		return hand.get(index);
	}

	/**
	 * Checks for one pair. Uses a nested for loop to check
	 * for the initial card matching. If any of the cards match,
	 * add to the counter and return true. Otherwise, return false.
	 */

	public boolean isPair() 
	{
		Collections.sort(hand);
		for (int x = 0; x < 5; x++) 
		{
			int y = 0;
			for (int i = 0; i < 5; i++) 
			{
				if (hand.get(i).getRank() == x) 
				{
					y++;
				}
			}
			if (y == 2) 
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * Checks for two pair. We first check if card one is equal to 
	 * card two, if so, we add one to our counter. Once counter
	 * reaches two, we have a two pair and return true.
	 * Otherwise, return false.
	 */

	public boolean isTwoPair() 
	{
		Collections.sort(hand);
		int counter = 0;

		if (hand.get(0).getRank() == hand.get(1).getRank()) 
		{
			counter++;
		}

		if (hand.get(2).getRank() == hand.get(3).getRank()) 
		{
			counter++;
		}

		if (counter == 2) 
		{
			return true;
		}
		return false;
	}

	/**
	 * Checks for three of a kind. Method is similar to isPair(),
	 * instead we look for three cards that are the same rank.
	 * If so, return true, otherwise, return false.
	 */

	public boolean isThreeOfAKind() 
	{
		Collections.sort(hand);

		for (int x = 0; x < 5; x++) 
		{
			int y = 0;
			for (int i = 0; i < 5; i++) 
			{
				if (hand.get(i).getRank() == x) 
				{
					y++;
				}
			}

			if (y == 3) // if three cards exist
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * Checks for straight, first we sort the hand. We then check if
	 * each card is equal to the next card in line.
	 */

	public boolean isStraight() 
	{
		Collections.sort(hand);

		if ((hand.get(4).getRank()) == 1) 
		{
			if ((hand.get(0).getRank()) == (hand.get(1).getRank() - 1)) 
			{
				if ((hand.get(1).getRank()) == (hand.get(2).getRank() - 1)) 
				{
					if ((hand.get(2).getRank()) == (hand.get(3).getRank() - 1)) 
					{
						return true;
					}
				}
			}
		} 
		else if ((hand.get(0).getRank()) == (hand.get(1).getRank() - 1)) 
		{
			if ((hand.get(1).getRank()) == (hand.get(2).getRank() - 1)) 
			{
				if ((hand.get(2).getRank()) == (hand.get(3).getRank() - 1)) 
				{
					if ((hand.get(3).getRank()) == (hand.get(4).getRank() - 1)) 
					{
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * Checks for flush. Methodology is similar to three of a kind.
	 * We assign a temp variable to each card's suit. If any of them
	 * do not match, we return false, otherwise, true.
	 */

	public boolean isFlush() 
	{
		Collections.sort(hand);

		int tempVar;
		for (int x = 0; x < 5; x++) 
		{
			tempVar = hand.get(x).getSuit();
			for (int y = 0; y < 5; y++) 
			{
				if (x != y) 
				{
					if (tempVar != (hand.get(y).getSuit())) 
					{
						return false;
					}
				}
			}
		}
		return true;
	}

	/**
	 * Checks for full house. Because we wrote methods to check for
	 * three of a kind and pair, we can simply use them to compare.
	 */

	public boolean isFullHouse() 
	{
		Collections.sort(hand);

		if (isThreeOfAKind() && isPair() == true) 
		{
			return true;
		}
		return false;
	}

	/**
	 * Checks for four of a kind. Use of nested for loop again,
	 * check the ranks of each card, if counter reaches 4, return true.
	 */

	public boolean isFourOfAKind() 
	{
		Collections.sort(hand);

		for (int x = 0; x < 5; x++) 
		{
			int y = 0;
			for (int i = 0; i < 5; i++) 
			{
				if (hand.get(i).getRank() == x) 
				{
					y++;
				}
			}
			if (y == 4) 
			{
				return true;
			}
		}
		return false;
	}

	/**
	 * Checks for straight flush. Compares both rank and suit of each card.
	 */

	public boolean isStraightFlush() 
	{
		Collections.sort(hand);

		if ((hand.get(4).getRank() == 1)
				&& (hand.get(4).getSuit() == (hand.get(3).getSuit()))) 
		{
			if ((hand.get(0).getSuit()) == (hand.get(1).getSuit())
					&& ((hand.get(0).getRank()) == (hand.get(1).getRank() - 1))) 
			{
				if ((hand.get(1).getSuit()) == (hand.get(2).getSuit())
						&& ((hand.get(1).getRank()) == (hand.get(2).getRank() - 1))) 
				{
					if ((hand.get(2).getSuit()) == (hand.get(3).getSuit())
							&& ((hand.get(2).getRank()) == (hand.get(3)
									.getRank() - 1))) 
					{
						return true;
					}
				}
			}

		} 
		else if ((hand.get(0).getSuit()) == (hand.get(1).getSuit())
				&& ((hand.get(0).getRank()) == (hand.get(1).getRank() - 1))) 
		{
			if ((hand.get(1).getSuit()) == (hand.get(2).getSuit())
					&& ((hand.get(1).getRank()) == (hand.get(2).getRank() - 1))) 
			{
				if ((hand.get(2).getSuit()) == (hand.get(3).getSuit())
						&& ((hand.get(2).getRank()) == (hand.get(3).getRank() - 1))) 
				{
					if ((hand.get(3).getSuit()) == (hand.get(4).getSuit())
							&& ((hand.get(3).getRank()) == (hand.get(4)
									.getRank() - 1)))
					{
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * Checks for royal flush. Chances of this are slim but we still
	 * need to account for it.
	 */

	public boolean isRoyalFlush() 
	{
		Collections.sort(hand);

		if (((hand.get(4).getRank()) == 1)
				&& ((hand.get(4).getSuit()) == (hand.get(3).getSuit()))) 
		{
			if (((hand.get(0).getRank()) == (hand.get(1).getRank() - 1))
					&& ((hand.get(0).getSuit()) == (hand.get(1).getSuit()))) 
			{
				if (((hand.get(1).getRank()) == (hand.get(2).getRank() - 1))
						&& ((hand.get(1).getSuit()) == (hand.get(2).getSuit()))) 
				{
					if (((hand.get(2).getRank()) == (hand.get(3).getRank() - 1))
							&& ((hand.get(2).getSuit()) == (hand.get(3)
									.getSuit())))
					{
						return true;
					}
				}
			}
		}
		return false;
	}
}
